package com.hl233.framework.utils;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.hl233.framework.config.MinioProp;
import io.minio.*;
import io.minio.Result;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
 *  * minio操作类
 * @author 张振强15065206763
 * @create 2025/4/24
 */
@Component
@Slf4j
public class MinIOUtil {

    @Resource
    private MinioProp minioProperties;

    private MinioClient minioClient;

    @Bean
    private MinioClient createMinioClient() {
        MinioClient client = MinioClient.builder().endpoint(minioProperties.getEndpoint())
                .credentials(minioProperties.getAccessKey(), minioProperties.getSecretKey())
                .build();
        this.minioClient = client;
        return client;
    }

    /**
     * 创建bucket
     * @param bucketName
     */
    public void createBucket(String bucketName) throws Exception {
        if (StringUtils.isBlank(bucketName)){
            // 存储桶名字不能为空
            System.out.println("存储桶名字不能为空");
            return;
        }
        minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
    }

    /**
     * 删除bucket
     * @param bucketName
     * @throws Exception
     */
    public void deleteBucket(String bucketName) throws Exception {
        if (StringUtils.isBlank(bucketName)){
            // 存储桶名字不能为空
            System.out.println("存储桶名字不能为空");
            return;
        }
        minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
    }

    /**
     * 判断bucket是否存在
     * @param bucketName
     * @return
     * @throws Exception
     */
    public boolean isExistBucket(String bucketName) throws Exception {
        if (StringUtils.isBlank(bucketName)){
            // 存储桶名字不能为空
            System.out.println("存储桶名字不能为空");
            return false;
        }
        return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
    }

    /**
     * 获取所有的存储桶信息
     * @return
     * @throws Exception
     */
    public List<Bucket> listBuckets() throws Exception {
        return minioClient.listBuckets();
    }

    /**
     * 获取存储桶中的某个文件夹下的所有文件
     * @param bucketName
     * @param folderName 文件夹名
     * @return
     */
    public Iterable<Result<Item>> getAllFileInBucket(String bucketName, String folderName){
        if (StringUtils.isBlank(bucketName)){
            System.out.println("存储桶名字不能为空");
            return null;
        }
        if (StringUtils.isBlank(folderName)){
            return minioClient.listObjects(ListObjectsArgs.builder().bucket(bucketName).build());
        }else {
            return minioClient.listObjects(ListObjectsArgs.builder().bucket(bucketName).prefix(folderName+"/").build());
        }
    }

    /**
     * 删除存储桶中文件夹
     * @param bucketName
     * @param folderName
     * @return
     */
    public boolean deleteFolderInBucket(String bucketName,String folderName){
        if (StringUtils.isBlank(bucketName)||StringUtils.isBlank(folderName)){
            System.out.println("存储桶名字或者文件夹名字不能为空");
            return false;
        }
        try {
            Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder().bucket(bucketName).prefix(folderName + "/").build());
            for (Result<Item> result : results) {
                Item item = result.get();
                minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(item.objectName()).build());
            }
            return true;
        } catch (Exception e) {
            System.out.println("删除文件夹失败");
            return false;
        }
    }

    /**
     * 删除根目录下的所有文件
     * @param bucketName
     * @return
     */
    public boolean deleteAllFileInRootPath(String bucketName){
        if (StringUtils.isBlank(bucketName)){
            System.out.println("存储桶名字不能为空");
            return false;
        }
        try {
            Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder().bucket(bucketName).build());
            for (Result<Item> result : results) {
                Item item = result.get();
                minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(item.objectName()).build());
            }
            return true;
        } catch (Exception e) {
            System.out.println("删除根目录下的所有文件失败");
            return false;
        }
    }

    /**
     * 获取文件下载地址
     * @param bucketName
     * @param objectName
     * @param expires
     * @return
     * @throws Exception
     */
    public String getFileDownloadUrl(String bucketName, String objectName, Integer expires) throws Exception {
        if (StringUtils.isBlank(bucketName)||StringUtils.isBlank(objectName)){
            System.out.println("存储桶名字或者文件名不能为空");
            return null;
        }
        GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder()
                // url的请求方式
                .method(Method.GET)
                .bucket(bucketName)
                .object(objectName)
                // 设置url过期时间
                .expiry(expires, TimeUnit.SECONDS)
                .build();
        String objectUrl = minioClient.getPresignedObjectUrl(args);
        return objectUrl;
    }

    /**
     * 上传文件
     * MultipartFile 上传
     * @param file
     * @param bucketName
     * @param objectName
     * @return
     * @throws Exception
     */
    public boolean uploadFileByMultipartFile(MultipartFile file, String bucketName, String objectName) throws Exception {
        if (file==null||file.getSize()==0||file.isEmpty()){
            System.out.println("文件不能为空");
            return false;
        }
        if (StringUtils.isBlank(bucketName)||StringUtils.isBlank(objectName)){
            System.out.println("存储桶名字或者文件名不能为空");
            return false;
        }
        String originalFilename = file.getOriginalFilename();
        originalFilename= UUID.randomUUID()+"_"+originalFilename;
        InputStream inputStream = file.getInputStream();
        long size = file.getSize();
        String contentType = file.getContentType();

        minioClient.putObject(
                PutObjectArgs.builder()
                        .bucket(bucketName)
                        .object(originalFilename)
                        // 第一个参数：输入流
                        // 第二个参数：文件大小
                        // 第三个参数：上传分片数量
                        .stream(inputStream, size, -1)
                        // 文件的类型
                        .contentType(contentType)
                        .build());
        return true;
    }

    public boolean uploadFileByMultipartFile(MultipartFile file, String objectName) throws Exception {
        if (file==null||file.getSize()==0||file.isEmpty()){
            System.out.println("文件不能为空");
            return false;
        }
        if (StringUtils.isBlank(objectName)){
            System.out.println("文件名不能为空");
            return false;
        }
        String originalFilename = file.getOriginalFilename();
        originalFilename= UUID.randomUUID()+"_"+originalFilename;
        InputStream inputStream = file.getInputStream();
        long size = file.getSize();
        String contentType = file.getContentType();

        minioClient.putObject(
                PutObjectArgs.builder()
                        .bucket(minioProperties.getBucketName())
                        .object(originalFilename)
                        // 第一个参数：输入流
                        // 第二个参数：文件大小
                        // 第三个参数：上传分片数量
                        .stream(inputStream, size, -1)
                        // 文件的类型
                        .contentType(contentType)
                        .build());
        return true;
    }

    /**
     * 上传本地文件
     * @param filePath
     * @param bucketName
     * @return
     * @throws Exception
     */
    public boolean uploadFileByLocalPath(String filePath, String bucketName) throws Exception {
        if (StringUtils.isBlank(filePath) || StringUtils.isBlank(bucketName)) {
            System.out.println("文件路径或者存储桶名字不能为空");
            return false;
        }

        File file = new File(filePath);
        if (!file.exists() || !file.canRead()) {
            System.out.println("文件不存在或者不可读");
            return false;
        }

        String minioFilename = UUID.randomUUID() + "_" + file.getName();
        String fileType = Files.probeContentType(file.toPath());

        try {
            minioClient.uploadObject(
                    UploadObjectArgs.builder()
                            .bucket(bucketName)
                            .object(minioFilename)
                            .filename(filePath)
                            .contentType(fileType)
                            .build());
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
}





